package org.activequant.data.retrieval.mappings;

import org.activequant.core.domainmodel.InstrumentSpecification;
import org.activequant.core.domainmodel.SeriesSpecification;
import org.activequant.core.domainmodel.data.TimeSeries;
import org.activequant.core.mappings.IInstrumentSpecificationMapper;
import org.activequant.data.retrieval.ISeriesDataSource;

/**
 * Supports symbol (and vendor) mappings.<br>
 * <br/>
 * An abstract class. SeriesSourceMappingProxy&lt;T extends TimeSeries&lt;?&gt;&gt; implements ISeriesDataSource&lt;T&gt;. Holds the following associated variables:
 * <ul>
 * <li>source(ISeriesDataSource&lt;T&gt;)</li>
 * <li>mapper(IInstrumentSpecificationMapper)</li>
 * </ul>
 * <b>History:</b><br>
 *  - [20.01.2008] Created (Erik Nijkamp)<br>
 *  
 *  @author Erik Nijkamp
 *
 */
public abstract class SeriesSourceMappingProxy<T extends TimeSeries<?>> implements ISeriesDataSource<T> {
	/**
	 * private ISeriesDataSource&lt;T&gt; source;
	 */
	private ISeriesDataSource<T> source;
	/**
	 * private IInstrumentSpecificationMapper mapper;
	 */
	private IInstrumentSpecificationMapper mapper;
	/**
	 * constructs a SeriesSourceMappingProxy&lt;T extends TimeSeries&lt;?&gt;&gt; (implements ISeriesDataSource&lt;T&gt;) using the given
	 * source(ISeriesDataSource&lt;T&gt;) and mapper(IInstrumentSpecificationMapper) to set its associated source(ISeriesDataSource&lt;T&gt;) and mapper(IInstrumentSpecificationMapper)
	 * @param source
	 * @param mapper
	 */
	public SeriesSourceMappingProxy(
			ISeriesDataSource<T> source, 
			IInstrumentSpecificationMapper mapper) {
		this.source = source;
		this.mapper = mapper;
	}
	/**
	 * <strong>1.</strong> Creates a clone seriesSpecTarget(SeriesSpecification) of the given seriesSpecTarget(SeriesSpecification) except its instrumentSpecification(InstrumentSpecification)
	 * is internalized using the associated mapper(IInstrumentSpecificationMapper).<br/>
	 * <strong>2.</strong> Fetches and returns the resulting TimeSeries&lt;?&gt; subclass for the cloned seriesSpecTarget(SeriesSpecification) (by invoking 
	 * <code>source.fetch(seriesSpecTarget)</code> on the associated source(ISeriesDataSource&lt;T&gt;))
	 */
	public T fetch(SeriesSpecification seriesSpecification) throws Exception {
		// clone
		SeriesSpecification seriesSpecTarget = new SeriesSpecification(seriesSpecification);
		// map
		InstrumentSpecification instrument = mapper.mapToInternal(seriesSpecification.getInstrumentSpecification());
		seriesSpecTarget.setInstrumentSpecification(instrument);
		// fetch
		T series = source.fetch(seriesSpecTarget);
		return series;
	}
}
